#ifndef PROCESSOR_CC
#define PROCESSOR_CC
#include <iostream>
#include <list>
#include <queue>
#include "Process.h"

using namespace std;



class Processor{
protected:



      //int numProcessors;
      //int numProcesses;
      int numQueues;


public:
queue<Process>** multipleQueue;
Process currentProcess;
list<Process>* finishedProcesses;
bool idle;
Processor(){
finishedProcesses= new list<Process>();
 multipleQueue = new queue<Process>*[0];
idle = true;
// numProcessors=0;
numQueues = 1;

}

Processor(queue<Process>** mq){
 multipleQueue = mq;
 numQueues = 1;
 finishedProcesses= new list<Process>();
 idle = true;
 //numProcessors=0;
}
Processor(queue<Process>** mq, int numQ){
 multipleQueue = mq;
 //numProcesses=0;
 numQueues = numQ;
 idle = true;
}

queue<Process>** get(){
 return multipleQueue;
}

void addQueueList(queue<Process>** mq, int numQueue){
 multipleQueue = mq;
 numQueues = numQueue;
}
void ageProcessor(){
	int size = multipleQueue[(numQueues - 1)]->size();
	queue<Process>* store = new queue<Process>();
	for (int i = 0; i<size; i++){
		store->push(multipleQueue[(numQueues - 1)]->front());
		multipleQueue[(numQueues - 1)]->pop();
		//cout<<"Adding process "<<store->back()<<" to store."<<endl;
		//cout<<"increasing age from "<<store->back().age<<" to "<<store->back().age+1<<endl;
		store->back().age++;
	}
	for(int i = 0; i < size;i++){
		//put back in last queue
		multipleQueue[(numQueues - 1)]->push(store->front());
		//cout<<"Adding process "<<multipleQueue[(numQueues - 1)]->back()<<" back to queue "<< numQueues-1<<endl;
		store->pop();
	}
}


void addPtoQ(Process p){
       cout<<"in addPtoQ"<<endl;
       cout<<"Numqueues: "<<numQueues<<endl;
       if (numQueues ==1){
               multipleQueue[0]->push(p);
       }else{
          for (int lcv=0; lcv<numQueues; lcv++){
                       if ((currentProcess.queueNumber != lcv)||(lcv==numQueues-1)){ // there is no current process in that queue, so add the process to that queue
                               cout<<"Adding process "<< p.PID <<" to Queue "<<lcv<<endl;
                               p.queueNumber = lcv;
                               multipleQueue[lcv]->push(p);
                               lcv=numQueues;

                       }
          }

       }

}


void setCurrentProcess(Process p){
      currentProcess =p;

}

Process getCurrentProcess(){
      return currentProcess;

}

bool isEmpty(){
       bool allempty = true;
       for(int lcv = 0; lcv < numQueues; lcv++){
       if(!multipleQueue[lcv]->empty()){
               allempty = false;
       }
       }
      return allempty;
}


int getNumProcesses(){
      int count = 0;
      for (int lcv=0; lcv<numQueues; lcv++){

              count = count + multipleQueue[lcv]->size();

      }
          if (currentProcess.PID >-1){
          count++;
          }

      return count;

}
int getNumWaitingProcesses(){
      int count = 0;
      for (int lcv=0; lcv<numQueues; lcv++){

              count = count + multipleQueue[lcv]->size();

      }

      return count;

}

Process getNextProcess(){
       int currentQ =currentProcess.queueNumber;
       Process p;
       if(multipleQueue[currentProcess.queueNumber]->size() > 0){
			   cout<<"In Queue "<<currentProcess.queueNumber<<"which is not empty."  <<endl;
               p = multipleQueue[currentProcess.queueNumber]->front();
               p.queueNumber = currentProcess.queueNumber;
			   cout<<"Getting Next Process " << p.PID<<endl;
			   multipleQueue[currentProcess.queueNumber]->pop();
			   
       }else{			
                       cout << "None in queue 0 check others " << endl;
                       for (int i =currentQ+1; i<numQueues; i++){

                               if (multipleQueue[i]->size()>0){
                                               cout << "Found Some Processes in queue " <<i<< endl;
                                               p = multipleQueue[i]->front();
											   cout<<"Getting Next Process " << multipleQueue[i]->front().PID<<endl;
                                               multipleQueue[i]->pop();
											   p.queueNumber = i;
											   i = numQueues;
                               }
                       }
               }
               return p;
}

  void display(ostream& os) const{
		int runningProcess = 1;
		if(idle){
				runningProcess = 0;
		}
		os << "--------------------" << endl;
		//os << "Running " << this->getNumProcesses() << " processes." << endl;
		os << "Currently executing: ";
		//if(!idle){
				if (currentProcess.PID!=-1){
				os << currentProcess;
				}else{
					cout<<"None"<<endl;
				}
		//} else {
				//os << " No Processes." << endl;
		//}                       
		Process startProcess;
		Process p;
		//list<queue<Process>**>::iterator i;
		//switch(method){
			//	case HRN:
				//		break;
				//case MFQS:
						//for(i = multipleQueue->begin();i != multipleQueue->end();i++){
						for (int lcv =0; lcv<numQueues; lcv++){
								cout << "\tQueue " << lcv << ": " << multipleQueue[lcv]->size() << " processes." << endl;
								if(!multipleQueue[lcv]->empty()){
										p = multipleQueue[lcv]->front();
										startProcess = p;
										cout << "\t\t" << p;
										multipleQueue[lcv]->pop();
										multipleQueue[lcv]->push(p);
										while(!multipleQueue[lcv]->empty() && (multipleQueue[lcv]->front().PID != startProcess.PID)){
												p = multipleQueue[lcv]->front();
												cout << "\t\t" << p;
												multipleQueue[lcv]->pop();
												multipleQueue[lcv]->push(p);
										}
								}

						}
						
				//		break;
				//case UNIX:
					//	cout << "Process information display not implemented." << endl;
					//	break;
	//	}
}
friend ostream& operator << (ostream& os, const Processor& theProcessor) {
                        theProcessor.display(os);
                        return os;
                }
};

#endif
